package com.filldream.fastboot.common.okutil;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 网格交易工具
 *
 */
public class StockGridUtil {

    /** 步长，可以是金额也可以是百分比 **/
    private static final BigDecimal DROP_STEP = new BigDecimal("1.55");
    /** 步长类型，true为金额，false为百分比 **/
    private static final Boolean STEP_TYPE = false;
    private static final int SCALE = 3;
    private static final RoundingMode ROUND_MODE = RoundingMode.DOWN;

    public static void main(String[] args) {
        //HSKJ
        {
            BigDecimal currentUnitPrice = new BigDecimal("0.784");
            BigDecimal currentStockUnitPrice = new BigDecimal("0.753");
            BigDecimal stopUnitPrice = new BigDecimal("0.386");
            BigDecimal currentNumber = new BigDecimal("2200");
            BigDecimal addNumber = new BigDecimal("200");
            BigDecimal totalCapital = new BigDecimal("4000");
            calculate(currentNumber, currentUnitPrice, totalCapital, addNumber, stopUnitPrice, currentStockUnitPrice);
        }

    }

    /**
     * 计算输出
     * @param currentNumber     当前持有数量
     * @param currentUnitPrice  当前持有单价
     * @param totalCapital      总可承受本金
     * @param addNumber         每次补仓数量
     * @param stopUnitPrice     停止单价
     * @param currentStockUnitPrice     当前单价/触发单价
     */
    public static void calculate(BigDecimal currentNumber, BigDecimal currentUnitPrice, BigDecimal totalCapital, BigDecimal addNumber, BigDecimal stopUnitPrice, BigDecimal currentStockUnitPrice) {
        // 初始化关键参数
        final BigDecimal initPrice = currentStockUnitPrice;
        int operationCount = 0;                     // 补仓次数
        BigDecimal remainingCapital = totalCapital.subtract(currentNumber.multiply(currentUnitPrice)); // 剩余本金
        BigDecimal totalCost = currentNumber.multiply(currentUnitPrice);     // 累计补仓成本
        BigDecimal avgPrice = currentUnitPrice;         // 当前平均成本
        BigDecimal totalShares = currentNumber;     // 总持股数

        printRow(operationCount, currentStockUnitPrice, totalShares, avgPrice, totalCost, remainingCapital, initPrice);

        // 主循环逻辑
        while (remainingCapital.compareTo(BigDecimal.ZERO) >= 0 && currentStockUnitPrice.compareTo(stopUnitPrice) > 0) {
            // 计算本次补仓价格
            BigDecimal buyPrice = currentStockUnitPrice.subtract(DROP_STEP).setScale(SCALE, ROUND_MODE);
            if( !STEP_TYPE ){
                BigDecimal yuan = BigDecimal.ONE.subtract(DROP_STEP.divide(new BigDecimal("100"),4,ROUND_MODE));
                buyPrice = currentStockUnitPrice.multiply( yuan ).setScale(SCALE, ROUND_MODE);
            }
            // 达到止跌价则终止
            if (buyPrice.compareTo(stopUnitPrice) < 0) break;
            // 计算本次补仓成本
            BigDecimal cost = buyPrice.multiply(addNumber).setScale(SCALE, ROUND_MODE);
            cost = cost.add( new BigDecimal("0.1") ); //手续费
            // 更新累计数据
            operationCount++;
            totalCost = totalCost.add(cost);
            remainingCapital = remainingCapital.subtract(cost);
            // 计算新的平均成本
            BigDecimal totalValue = totalShares.multiply(avgPrice).add(addNumber.multiply(buyPrice));
            totalShares = totalShares.add(addNumber);
            avgPrice = totalValue.divide(totalShares, 4, ROUND_MODE);
            // 更新当前价格
            currentStockUnitPrice = buyPrice;
            if (remainingCapital.compareTo(BigDecimal.ZERO) >= 0) {
                printRow(operationCount, buyPrice, totalShares, avgPrice, totalCost, remainingCapital, initPrice);
            }
        }

    }

    /**
     * 打印输出
     * @param count     补仓数量
     * @param price     补仓单价
     * @param shares    总持有数
     * @param avgPrice  平均成本
     * @param totalCost 已用成本
     * @param remaining 剩余成本
     * @param initPrice 初始单价
     */
    private static void printRow(int count, BigDecimal price, BigDecimal shares, BigDecimal avgPrice, BigDecimal totalCost, BigDecimal remaining, BigDecimal initPrice) {
        //计算跌幅
        BigDecimal df = count == 0 ? BigDecimal.ZERO : BigDecimal.ONE.subtract(price.divide(initPrice, 4, ROUND_MODE)).multiply(new BigDecimal("100")).setScale(2, ROUND_MODE);
        System.out.println(
                (count == 0 ? "初始持仓:" : "补仓次数:") + (count < 10 ? "0" + count : count)
                        + "\t" + (count == 0 ? "初始单价:" : "补仓价格:") + price
                        + "\t平均成本:" + avgPrice.setScale(4, ROUND_MODE)
                        + "\t补仓差价:" + (avgPrice.subtract(price)).setScale(SCALE, ROUND_MODE)
                        + "\t总持有数:" + shares
                        + "\t已用成本:" + totalCost.setScale(2, ROUND_MODE)
                        + "\t剩余成本:" + remaining.setScale(2, ROUND_MODE)
                        + "\t原始差价:" + ( initPrice.subtract(price) )
                        + "\t总共跌幅:" + df + "%"
                        + "\t总亏损额:" + ((avgPrice.subtract(price)).setScale(SCALE-1, ROUND_MODE)).multiply(shares)
        );
    }

}